using System;
using System.Reflection;
using System.Collections.Generic;

namespace Pvp.Ecs
{
    public sealed class Entity
    {
        private int entityId;
        private Dictionary<Type,IDataComponent> _entityMap;

        private Entity(int id)
        {
            entityId = id;
            _entityMap = new Dictionary<Type, IDataComponent>();
        }

        private bool HasComponent<T>(out T value) where  T : IDataComponent
        {
            IDataComponent tmp = null;
            bool result = _entityMap.TryGetValue(typeof(T),out tmp);
            value = (T)tmp;
            return result;
        }

        public static void CreateEntity(int entityType, int subType,object userData = null)
        {
            var entity = EntityCreator.CreateEntity(entityType,subType,userData);
            foreach (var kvp in entity.Key._entityMap)
            {
                kvp.Value.BelongEntityId = entity.Key.entityId;
                
                Entities.AddComponent(kvp.Key,kvp.Value);
            }

            if (entity.Key.HasComponent<IView>(out var view))
            {
                view.EntityType = entity.Value.Key;
                view.SubType = entity.Value.Value;
                ViewUtility.CreateView(view);
            }
        }

        public T AddComponent<T>() where T : IDataComponent,new()
        {
            var t = new T();
            _entityMap.Add(typeof(T),t);
            return t;
        }
        
        
        static class EntityCreator
        {
            private static int _EntityIndex = 1001;
            private static Dictionary<KeyValuePair<int,int>, Type> _entityDeclareMap;

            public static KeyValuePair<Entity,KeyValuePair<int,int>> CreateEntity(int entityType,int subType,object userData)
            {
                var entry = new Entity(_EntityIndex++);
                if (_entityDeclareMap.TryGetValue(new KeyValuePair<int, int>(entityType, subType), out var x))
                {
                    var inst = (BaseEntityDeclare) System.Activator.CreateInstance(x);
                    inst.OnEntityCreate(entry, userData);
                }
                return new KeyValuePair<Entity, KeyValuePair<int, int>>(entry,new KeyValuePair<int, int>(entityType,subType));
            }

            static EntityCreator()
            {
                _entityDeclareMap = new Dictionary<KeyValuePair<int, int>, Type>();
                var types = typeof(EntityCreator).Assembly.GetTypes();
                foreach (var type in types)
                {
                    var attr = type.GetCustomAttribute<EntityDeclareAttribute>();
                    if (attr != null && type.IsSubclassOf(typeof(BaseEntityDeclare)))
                    {
                        _entityDeclareMap.Add(new KeyValuePair<int, int>(attr.entityType, attr.entitySubType), type);
                    }
                }
            }
        }
    }
}